#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_qipan(new qipan),
    m_timer(new QTimer(this))
{
    ui->setupUi(this);

    m_isPlayerTurn = true;

    m_timer->setInterval(5000);

    /* 初始化随机数种子 */
    srand(time(NULL));

    /* 设置窗口图标 */
    setWindowIcon(QIcon(":/imp/OIP-C.jpg"));
    /* 设置标题 */
    setWindowTitle("五子棋对战");

    /* 设置窗口的固定大小 */
    setFixedSize(800, 640);

    /* 设置布局 —— 解决棋盘绘制问题 */
    QWidget * centerWidget = new QWidget(this);
    setCentralWidget(centerWidget);
    QVBoxLayout *layout = new QVBoxLayout(centerWidget);
    layout->addWidget(m_qipan);

    /* 接受信号 */
    connect(m_qipan, &qipan::cellClicked, this, &MainWindow::handleCellClicked);

    connect(m_timer, &QTimer::timeout, this, &MainWindow::handleTimeOut);

    QPushButton *startBtn = new QPushButton("开始游戏", this);
    startBtn->move(640, 100);
    startBtn->resize(120, 60);

    QPushButton *restartBtn = new QPushButton("重新开始", this);
    restartBtn->move(640, 200);
    restartBtn->resize(120, 60);

    QPushButton *backBtn = new QPushButton("悔棋", this);
    backBtn->move(640, 300);
    backBtn->resize(120, 60);

    connect(startBtn, &QPushButton::clicked, this, &MainWindow::handleStartSlot);
    connect(restartBtn, &QPushButton::clicked, this, &MainWindow::handleRestartSlot);
    connect(backBtn, &QPushButton::clicked, this, &MainWindow::handleRepentance);
}

void MainWindow::handleStartSlot()
{
    qDebug() << "开始游戏的按钮被点击了" << endl;
    for (int idx = 0; idx < m_qipan->getBoardSize(); idx++)
    {
        for (int jdx = 0; jdx < m_qipan->getBoardSize(); jdx++)
        {
            m_qipan->setPointVal(idx, jdx, EMPTY);
        }
    }
}

void MainWindow::handleRestartSlot()
{
    qDebug() << "重新开始的按钮被点击了" << endl;
    for (int idx = 0; idx < m_qipan->getBoardSize(); idx++)
    {
        for (int jdx = 0; jdx < m_qipan->getBoardSize(); jdx++)
        {
            m_qipan->setPointVal(idx, jdx, EMPTY);
        }
    }
    m_isPlayerTurn = true;
}

void MainWindow::handleRepentance()
{
    qDebug() << "悔棋" << endl;
    m_qipan->setPointVal(m_delayRow, m_delayCol, EMPTY);
    m_qipan->setPointVal(m_clickRow, m_clickCol, EMPTY);
}

void MainWindow::handleCellClicked(int row, int col)
{
    if (m_qipan->getPointVal(row, col) == 0)
    {
        /* 确定当前玩家 */
        Role role = m_isPlayerTurn ? PLAYER : NPC;

        if (role == PLAYER)
        {
            m_qipan->setPointVal(row, col, role);
            m_clickRow = row;
            m_clickCol = col;
            m_qipan->update();

            /* 判断玩家有没有获胜 */
            if (m_qipan->isCheckWin(row, col, role) == true)
            {
                QMessageBox::information(this, "游戏结束", "玩家获胜");
                m_isPlayerTurn = !m_isPlayerTurn;
                for (int idx = 0; idx < m_qipan->getBoardSize(); idx++)
                {
                    for (int jdx = 0; jdx < m_qipan->getBoardSize(); jdx++)
                    {
                        if (m_qipan->getPointVal(idx, jdx) == 0)
                        {
                            m_qipan->setPointVal(idx, jdx, STOP);
                        }
                    }
                }
            }
            else
            {
                /* 人机下棋 */
                m_isPlayerTurn = !m_isPlayerTurn;
                if (m_isPlayerTurn == false)
                {
                    NPCMove();
                }
            }
        }
    }
}

void MainWindow::handleTimeOut()
{
    /* 停止定时器 */
    m_timer->stop();

    m_qipan->setPointVal(m_delayRow, m_delayCol, NPC);

    m_qipan->update();

    if (m_qipan->isCheckWin(m_delayRow, m_delayCol, NPC) == true)
    {
        QMessageBox::information(this, "游戏结束", "人机获胜");
        for (int idx = 0; idx < m_qipan->getBoardSize(); idx++)
        {
            for (int jdx = 0; jdx < m_qipan->getBoardSize(); jdx++)
            {
                if (m_qipan->getPointVal(idx, jdx) == 0)
                {
                    m_qipan->setPointVal(idx, jdx, STOP);
                }
            }
        }
    }
    else
    {
        m_isPlayerTurn = !m_isPlayerTurn;
    }
}

void MainWindow::NPCMove()
{
    int bestScore = -1;
    int bestRow = -1;
    int bestCol = -1;

    for (int row = 0; row < qipan::getBoardSize(); row++)
    {
        for (int col = 0; col < qipan::getBoardSize(); col++)
        {
            if (m_qipan->getPointVal(row, col) == 0)
            {
                int score = evaluateValue(row, col, NPC) + evaluateValue(row, col, PLAYER);
                if (score > bestScore)
                {
                    bestScore = score;
                    bestRow = row;
                    bestCol = col;
                }
            }
        }
    }

    if (bestRow != -1 && bestCol != -1)
    {
        m_delayRow = bestRow;
        m_delayCol = bestCol;

        int randNum = rand() % 500 + 500;
        m_timer->start(randNum);
    }
}

int MainWindow::evaluateValue(int row, int col, Role role)
{
    int score = 0;

    /* 四个方向 */
    int directions[4][2] =
    {
        {1, 0},     //水平
        {0, 1},     //垂直
        {1, -1},    //左下右上
        {1, 1}      //右上左下
    };

    /* 遍历四个方向 */
    /* 遍历每个方向 */
    for (int direct = 0; direct < 4; direct++)
    {
        /* 初始计数 */
        int cnt = 0;        //连子数
        int openEnd = 0;    //开放端

        /* 向一个方向探测 */
        for (int idx = 1; idx < 5; idx++)
        {
            int newRow = row + directions[direct][0] * idx;
            int newCol = col + directions[direct][1] * idx;

            if ((newRow >= 0 && newRow < qipan::getBoardSize()) && (newCol >= 0 && newCol < qipan::getBoardSize()))
            {
                if (m_qipan->getPointVal(newRow, newCol) == role)
                {
                    cnt++;
                }
                else if (m_qipan->getPointVal(newRow, newCol) == 0)
                {
                    openEnd++;
                    break;
                }
                else
                {
                    break;
                }
            }
            else
            {
                break;
            }
        }

        /* 向反方向探测 */
        for (int idx = 1; idx < 5; idx++)
        {
            int newRow = row - directions[direct][0] * idx;
            int newCol = col - directions[direct][1] * idx;

            if ((newRow >= 0 && newRow < qipan::getBoardSize()) && (newCol >= 0 && newCol < qipan::getBoardSize()))
            {
                if (m_qipan->getPointVal(newRow, newCol) == role)
                {
                    cnt++;
                }
                else if (m_qipan->getPointVal(newRow, newCol) == 0)
                {
                    openEnd++;
                    break;
                }
                else
                {
                    break;
                }
            }
            else
            {
                break;
            }
        }

        if (cnt == 4 && openEnd > 0)
        {
            score = 1000;
        }
        else if (cnt == 3 && openEnd > 0)
        {
            score = 100;
        }
        else if (cnt == 2 && openEnd > 0)
        {
            score = 10;
        }
        else if (cnt == 1 && openEnd > 0)
        {
            score = 1;
        }
    }

    return score;
}

MainWindow::~MainWindow()
{
    delete ui;
}
